import fs from 'fs';
import { resolve } from 'path';
import lessToJS from 'less-vars-to-js';

import legacy from '@vitejs/plugin-legacy';
import react from '@vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';

import { splitVendorChunkPlugin } from 'vite';
import vitePluginMkcert from 'vite-plugin-mkcert';
import vitePluginInspect from 'vite-plugin-inspect';
import vitePluginImp from 'vite-plugin-imp';
import vitePluginCompression from 'vite-plugin-compression';
import vitePluginSvgr from 'vite-plugin-svgr';
import { visualizer } from 'rollup-plugin-visualizer';

import type { UserConfigFn, UserConfig } from 'vite';
import { default as proxy } from './vite.proxy.config';

const pathResolver = (path: string) => resolve(__dirname, path);
const themeVariables = lessToJS(fs.readFileSync(pathResolver('./src/assets/styles/variables.less'), 'utf8'));

const commonConfig: UserConfig = {
  cacheDir: './.cache',
  clearScreen: false,
  envDir: './.env',
  envPrefix: 'EP_',
  server: {
    port: 3000,
    strictPort: true,

    https: true,
    open: true,
    proxy,
  },
  build: {
    sourcemap: false,
    rollupOptions: {
      output: {
        manualChunks: {
          'dll-react': ['react', 'react-dom'],
          'dll-main': ['mobx', 'moment'],
          'dll-kits': ['react-responsive', 'axios', 'classnames'],
        },
      },
    },
  },
  define: {
    'process.env': {},
  },

  plugins: [
    tsconfigPaths(),

    // polyfill related
    legacy({
      // TODO specify user agent broswer core
      targets: ['Chrome >= 92'],
      modernPolyfills: ['es.promise'],
      additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
      renderLegacyChunks: false,
    }),

    // style related

    // https related
    vitePluginMkcert({
      source: 'coding',
    }) as any,

    // svgr related
    vitePluginSvgr(),

    // deos related
    vitePluginImp({
      libList: [
        {
          libName: '@antv/x6-react-components',
          style: name => {
            return `@antv/x6-react-components/es/${name}/style/index.css`;
          },
        },
        {
          libName: 'react-contexify',
          replaceOldImport: false,
          style: () => {
            return 'react-contexify/dist/ReactContexify.css';
          },
        },
        {
          libName: 'react-grid-layout',
          replaceOldImport: false,
          style: () => {
            return ['react-grid-layout/css/styles.css', 'react-resizable/css/styles.css'];
          },
        },
      ],
    }),

    splitVendorChunkPlugin(),
  ],

  css: {
    modules: {
      localsConvention: 'camelCase',
    },
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
        modifyVars: themeVariables,
      },
    },
  },

  resolve: {
    alias: {
      '~antd': 'node_modules/antd',
      'Images/': 'src/assets/images/',
      'Styles/': 'src/assets/styles/',
      events: 'node_modules/rollup-plugin-node-polyfills/polyfills/events.js',
      '@antv/graphin': 'node_modules/@antv/graphin/lib',
    },
  },

  optimizeDeps: {
    include: [
      '@ant-design/pro-components',
      // x6 related
      'mousetrap',
      'jquery',
      'jquery-mousewheel',
    ],
    exclude: ['@antv/graphin', '@antv/x6', '@antv/x6-react-shape'],
  },
};

// https://vitejs.dev/config/
const defineConfig: UserConfigFn = ({ command, mode }) => {
  let config: UserConfig = { ...commonConfig };

  if (command === 'serve') {
    config = {
      ...config,

      base: './',
      plugins: [...config.plugins!, vitePluginInspect()],
    };
  }

  if (command === 'build' || mode === 'analyze') {
    config = {
      ...config,

      base: '/',
      plugins: [
        ...config.plugins!,

        react({
          babel: {
            parserOpts: {
              plugins: ['decorators-legacy', 'classProperties'],
            },
          },
        }),
        vitePluginCompression({
          algorithm: 'brotliCompress',
        }),
      ],
    };
  }

  if (mode === 'analyze') {
    config = {
      ...config,

      plugins: [
        ...config.plugins!,

        visualizer({
          filename: './.cache/visualizer/stats.html',
          gzipSize: true,
          brotliSize: true,
        }) as any,
      ],
    };
  }

  if (mode === 'staging') {
    config = {
      ...config,

      base: './',
      plugins: [...config.plugins!, react()],
    };
  }

  return config;
};

export default defineConfig;
